

import java.util.Iterator;
import java.util.List;
import java.util.Collection;


import jason.asSemantics.Event;
import jason.asSyntax.ListTerm;
import jason.asSyntax.Literal;
import jason.asSyntax.NumberTerm;
import jason.asSyntax.StringTerm;
import jason.asSyntax.Structure;
import jason.asSyntax.Term;
import jason.asSyntax.VarTerm;

/**
 * Helper to term convertion
 * @author Marcos
 *
 */
public class TermHelper 
{
	public static String getString(Literal lit, int pos)
	{
		if(pos < lit.getTerms().size())
		{
			return toString(lit.getTerm(pos));
		}else
			return "";
	}
	
	public static String toString(Term term)
	{
		if(term.isString())
			return ((StringTerm)term).getString();
		else
			return term.toString();
	}
	
	public static int getInteger(Literal lit, int pos) {
		if(pos < lit.getTerms().size())
		{
			return toInteger(lit.getTerm(pos));
		}else
		{
			return 0;
		}
	}
	
	public static double getDouble(Literal lit, int pos)
	{
		if(pos < lit.getTerms().size())
		{
			return toDouble(lit.getTerm(pos));
		}else
		{
			return 0.0;
		}
	}
	public static int toInteger(Term term)
	{
		if(term.isNumeric())
		{
			NumberTerm nt = (NumberTerm)term;
			return (int)nt.solve();
		}else if(term.isString())
		{
			String t = ((StringTerm)term).getString();
			try
			{
				return Integer.parseInt(t);
			}catch(Exception e)
			{
				return 0;
			}
		}else if(term.isVar())
		{
			VarTerm vt = (VarTerm) term;
			if(vt.getValue()!= null && vt.getValue().isNumeric())
			{
				NumberTerm nt = (NumberTerm)vt.getValue();
				return (int)nt.solve();
			}
		}
		return 0;
	}
	public static double toDouble(Term term)
	{
		if(term.isNumeric())
		{
			NumberTerm nt = (NumberTerm)term;
			return nt.solve();
		}else if(term.isString())
		{
			String t = ((StringTerm)term).getString();
			try
			{
				return Double.parseDouble(t);
			}catch(Exception e)
			{
				return 0;
			}
		}else if(term.isVar())
		{
			VarTerm vt = (VarTerm) term;
			if(vt.getValue()!= null && vt.getValue().isNumeric())
			{
				NumberTerm nt = (NumberTerm)vt.getValue();
				return nt.solve();
			}
		}
		return 0;
	}

	public static Literal generateLiteral(String functor, Object... vecObj) 
	{
		StringBuffer sb = new StringBuffer();
		sb.append(functor);
		sb.append("(");
		for(int i = 0; i < vecObj.length-1; i++)
		{
			sb.append(vecObj[i].toString());
			sb.append(", ");
		}
		
		sb.append(vecObj[vecObj.length-1].toString());
		sb.append(")");
		return Literal.parseLiteral(sb.toString());
	}

	public static List<String> getStrings(Term termParent, List<String> list) 
	{
		if(termParent.isList())
		{
			ListTerm lt = (ListTerm)termParent;
			return getStrings(lt.getAsList(), list);
		}else
		{
			return list;
		}
		
	}
	public static List<String> getStrings(List<Term> terms, List<String> list) {
		for(Term t: terms)
		{
			list.add(toString(t));
		}
		return list;
	}

	public static Collection<Term> toCollTerm(Structure action, int i) {
		Term temp = action.getTerm(i);
		List<Term> list = null;
		if(temp.isList())
		{
			list = ((ListTerm)temp).getAsList();
		}else if(temp.isStructure())
		{
			list = ((Structure)temp).getTerms();
		}
		
		return list;
	}

	/**
	 * Verifica se na enumeração existe algum elemento similar a query usada.
	 * @param enumeration
	 * @return
	 */
	
	public static Literal contain(final Iterable<Literal> iterable, final Literal query)
	{
		final int sizeQuery = query.getTerms().size();
		for(Literal temp: iterable)
		{
			if(temp.getTerms().size() == sizeQuery)
			{
				
				if(query.getFunctor().equals(temp.getFunctor()))
				{
					int i = 0;
					for(i = 0; i < sizeQuery; i++)
					{
						Term querySubTerm = query.getTerm(i);
						if(querySubTerm.isGround())
						{
							if(!querySubTerm.equals(temp.getTerm(i)))
							{
								break; //not is equals
							}
						}
					}
					
					if(i == sizeQuery)
						return temp;
				}
			}
		}
		
		return null;
	}

	public static Literal containDesire(final Iterable<Event> events,
			Literal parseLiteral) {
		
		Iterable<Literal> iterable = new Iterable<Literal>() {
			
			@Override
			public Iterator<Literal> iterator() {
				return new Iterator<Literal>()
						{
							Iterator<Event> base = events.iterator();
							@Override
							public boolean hasNext() {
								return base.hasNext();
							}

							@Override
							public Literal next() {
								Event event = base.next();
								return event.getTrigger().getLiteral();
							}

							@Override
							public void remove() {
								base.remove();
							}
					
						};
			}
		};
		return TermHelper.contain(iterable, parseLiteral);
	}

}
